package com.xbai.bean.definition;

import com.xbai.domain.User;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;

/**
 * @author jxbai
 * @desc {@link org.springframework.beans.factory.config.BeanDefinition} 注册示例
 * @date 2021/1/26
 */
// 3.通过 @Import 进行导入
@Import(BeanDefinitionRegisterDemo.Config.class)
public class BeanDefinitionRegisterDemo {

    public static void main(String[] args) {
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 配置类方式 注册 Configuration Class（配置类）
        applicationContext.register(BeanDefinitionRegisterDemo.Config.class);

        // 通过 BeanDefinition 注册 API 实现
        // 1.命名 Bean 的注册方式
        registerUserBeanDefinition(applicationContext, "api-register-user");
        // 2.非命名 Bean 的注册方式
        registerUserBeanDefinition(applicationContext);

        // 启动 Spring 应用上下文
        applicationContext.refresh();
        // 按照类型依赖查找
        System.out.println("Config 类型的所有 Beans：" + applicationContext.getBeansOfType(Config.class));
        System.out.println("User 类型的所有 Beans：" + applicationContext.getBeansOfType(User.class));

        // 显示的关闭 Spring 应用上下文
        applicationContext.close();
    }

    private static void registerUserBeanDefinition(BeanDefinitionRegistry registry) {
        registerUserBeanDefinition(registry, null);
    }

    private static void registerUserBeanDefinition(BeanDefinitionRegistry registry, String beanName) {
        BeanDefinitionBuilder beanDefinitionBuilder = genericBeanDefinition(User.class);
        beanDefinitionBuilder.addPropertyValue("id", 2L).addPropertyValue("name", "xbai2");
        // 判断 beanName 参数是否存在
        if (StringUtils.hasText(beanName)) {
            // 命名方式注册 BeanDefinition
            registry.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
        } else {
            // 非命名方式注册 BeanDefinition
            BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinitionBuilder.getBeanDefinition(), registry);
        }
    }

    /**
     * 2.通过 @Component 方式，定义当前类作为 Spring Bean（组件）
     */
    @Component
    public static class Config {
        /**
         * 1.通过 @Bean 方式定义
         * 通过 Java 注解的方式，定义了一个 Bean
         *
         * @return user 对象，名称为 user, 别名为 xbai-user
         */
        @Bean(name = {"user", "xbai-user"})
        public User user() {
            User user = new User();
            user.setId(1L);
            user.setName("xbai");
            return user;
        }
    }
}
